package ch09
{
	import flash.display.Sprite;
	import flash.display.StageAlign;
	import flash.display.StageScaleMode;
	import flash.events.Event;
	import flash.utils.setTimeout;

	import utils.Ball;

	/**
	 * 弹性碰撞.
	 * 如果小球与 centerBall 发生碰撞，就把小球弹出去，通过设置 centerBall 外面的目标点来实现，然后让小球向目标点弹性运动。
	 * 一旦小球到达目标，就不再产生碰撞，弹性运动结束，继续执行常规的运动。
	 *
	 * 当ball速度很快时，程序有BUG，效果是ball会嵌入中心圆球中，
	 * 但是将ball的x,y设定为临界碰撞位置，效果也有问题。
	 * @author sjp
	 *
	 */
	public class Bubbles extends Sprite
	{
		private var balls:Array;
		private var numBalls:Number=10;
		private var centerBall:Ball;
		private var bounce:Number=-1;
		private var spring:Number=0.2;

		public function Bubbles()
		{
			init();
		}

		private function init():void
		{
			stage.scaleMode=StageScaleMode.NO_SCALE;
			stage.align=StageAlign.TOP_LEFT;
			setTimeout(start, 500);

		}

		private function start():void
		{
			balls=new Array();
			centerBall=new Ball(100, 0xcccccc);
			addChild(centerBall);
			centerBall.x=stage.stageWidth / 2;
			centerBall.y=stage.stageHeight / 2;
			for (var i:uint=0; i < numBalls; i++)
			{
				var ball:Ball=new Ball(Math.random() * 40 + 5, Math.random() * 0xffffff);
				ball.x=Math.random() * stage.stageWidth;
				ball.y=Math.random() * stage.stageHeight;
				ball.vx=Math.random() * 6 - 3;
				ball.vy=Math.random() * 6 - 3;
				addChild(ball);
				balls.push(ball);
			}
			addEventListener(Event.ENTER_FRAME, onEnterFrame);
		}

		private function onEnterFrame(event:Event):void
		{
			for (var i:uint=0; i < numBalls; i++)
			{
				var ball:Ball=balls[i];

				var dx:Number=ball.x - centerBall.x;
				var dy:Number=ball.y - centerBall.y;
				var dist:Number=Math.sqrt(dx * dx + dy * dy);
				var minDist:Number=ball.radius + centerBall.radius;
				/**
				 * 碰撞发生后，其实位置已经<最小位置，设定目标位置为发生碰撞的最小位置，
				 * 然后使得ball向该点移动。
				 * 当ball速度很快时，程序有BUG，效果是ball会嵌入中心圆球中，
				 * 但是将ball的x,y设定为临界碰撞位置，效果也有问题。
				 * */
				if (dist < minDist)
				{
					var angle:Number=Math.atan2(dy, dx);
					var tx:Number=centerBall.x + Math.cos(angle) * minDist;
					var ty:Number=centerBall.y + Math.sin(angle) * minDist;
					ball.vx+=(tx - ball.x) * spring;
					ball.vy+=(ty - ball.y) * spring;
				}
				move(ball);
			}
		}

		private function move(ball:Ball):void
		{
			ball.x+=ball.vx;
			ball.y+=ball.vy;
			if (ball.x + ball.radius > stage.stageWidth)
			{
				ball.x=stage.stageWidth - ball.radius;
				ball.vx*=bounce;
			}
			else if (ball.x - ball.radius < 0)
			{
				ball.x=ball.radius;
				ball.vx*=bounce;
			}
			if (ball.y + ball.radius > stage.stageHeight)
			{
				ball.y=stage.stageHeight - ball.radius;
				ball.vy*=bounce;
			}
			else if (ball.y - ball.radius < 0)
			{
				ball.y=ball.radius;
				ball.vy*=bounce;
			}
		}
	}
}